package com.akk.business;

import com.akk.PayConstants;
import com.akk.common.enums.Enums;
import com.akk.module.access.entity.Access;
import com.akk.module.access.entity.AccessBind;
import com.akk.module.access.service.AccessService;
import com.akk.module.avs.entity.*;
import com.akk.module.avs.enums.AvsPayVipStatus;
import com.akk.module.avs.enums.AvsTransferStatus;
import com.akk.module.avs.service.*;
import com.akk.module.hlbpay.model.HlbTransferQueryResponse;
import com.akk.module.yb.model.*;
import com.akk.module.yb.service.YbService;
import com.akk.utils.IDUtils;
import com.akk.utils.RestResponse;
import com.akk.utils.exception.BusinessException;
import com.google.gson.Gson;
import org.apache.commons.httpclient.HttpStatus;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Component
public class AvsYbPayBusiness {

    @Autowired
    private YbService ybService;
    @Autowired
    private AvsCustomerService customerService;
    @Autowired
    private AvsPayCashBindService cashBindService;
    @Autowired
    private AvsPayOrderService orderService;
    @Autowired
    private AccessService accessService;
    @Autowired
    private AvsPayAccessService avsPayAccessService;
    @Autowired
    private AvsPayVipService vipService;
    @Value("${server.url}")
    private String serverUrl;
    @Value("${yb.photo}")
    private String photoPath;

    public RestResponse register(String payerId, String orderNum, String cashBindId, String type) {
        AvsCustomer customer = customerService.findByCustomerId(payerId);
        if (customer == null)
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "用户信息不存在");
        List<AvsPayCashBind> cashBind = cashBindService.findByCashBinIdAndIsDeposit(payerId, 1);
        if (cashBind.isEmpty())
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "未绑定结算卡信息");
        if (customer.getYbSubMerId() != null && customer.getYbSubMerId().length() > 3) {
            return receiveApi(customer, orderNum, cashBindId, type);
        }
        RegisterRequest request = new RegisterRequest();
        request.setRequestId(IDUtils.getUniqueNum14());
        request.setCustomerType("PERSON");
        request.setBindMobile(customer.getPhone());
        request.setSignedName(customer.getCustomerName());
        request.setLinkMan("极速收款");
        request.setIdCard(customer.getIdCard());
        request.setLegalPerson(customer.getCustomerName());
        request.setMinSettleAmount("1");
        request.setRiskReserveDay("0");
        request.setBankAccountNumber(cashBind.get(0).getCardNum());
        request.setBankName(cashBind.get(0).getBankName());
        request.setAccountName(customer.getCustomerName());
        request.setAreaCode("1000");
        request.setBankCardPhoto(photoPath);
        request.setIdCardBackPhoto(photoPath);
        request.setIdCardPhoto(photoPath);
        request.setBusinessLicensePhoto(photoPath);
        request.setPersonPhoto(photoPath);
        request.setMainCustomerNumber(PayConstants.YB_AGENT_NUMBER);
        request.setWhiteList("1");
        request.setManualSettle("Y"); // 关闭T1自动结算
        RestResponse restResponse = ybService.register(request);
        if (restResponse.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
            // 审核
            AuditMerchantRequest merchantRequest = new AuditMerchantRequest();
            merchantRequest.setCustomerNumber(restResponse.getResult().toString());
            merchantRequest.setStatus("SUCCESS");
            RestResponse merRestResponse = ybService.auditMerchant(merchantRequest);
            if (merRestResponse.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
                customer.setYbSubMerId(restResponse.getResult().toString());
                customerService.update(customer);
            }
            // 设置额外提现手续费0
            // T0自助结算 非工作日额外
            RestResponse setFeeResult = updateMerRate(customer.getYbSubMerId(), "5", "0");
            if (!setFeeResult.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
                return setFeeResult;
            }
            // T0自助结算 工作日额外
            setFeeResult = updateMerRate(customer.getYbSubMerId(), "4", "0");
            if (!setFeeResult.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
                return setFeeResult;
            }
            // T0自助结算
            setFeeResult = updateMerRate(customer.getYbSubMerId(), "3", "5");
            if (!setFeeResult.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
                return setFeeResult;
            }
            // T1自助结算
            setFeeResult = updateMerRate(customer.getYbSubMerId(), "2", "0");
            if (!setFeeResult.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
                return setFeeResult;
            }
            // 标准版
            setFeeResult = updateMerRate(customer.getYbSubMerId(), "1", "0.0038");
            if (!setFeeResult.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
                return setFeeResult;
            }
            // 专业版
            setFeeResult = updateMerRate(customer.getYbSubMerId(), "7", "0.0028");
            if (!setFeeResult.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
                return setFeeResult;
            }
            return receiveApi(customer, orderNum, cashBindId, type);
        }
        return restResponse;
    }

    // 刷卡支付
    public RestResponse receiveApi(AvsCustomer customer, String orderNum, String cashBindId, String type) {
        List<AvsPayOrder> orders = orderService.findByOrderNum(orderNum);
        if (orders.isEmpty())
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "订单信息不存在");
        AccessBind accessBind = accessService.findAccessBindById(cashBindId);
        if (accessBind == null)
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "银行卡信息不存在");
        AvsPayOrder order = orders.get(0);
        order.setPayCardNo(accessBind.getCardNum());
        order.setPayBank(accessBind.getCardName());
        orderService.update(order);
        ReceiveRequest request = new ReceiveRequest();
        request.setAmount(orders.get(0).getAmountTotal().toString());
        request.setCustomerNumber(customer.getYbSubMerId());
        request.setRequestId(orderNum);
        request.setSource("B");
        request.setMcc("5311");
        DecimalFormat format = new DecimalFormat("#.000000");
        Double rate;    // 手续费
        Integer deposit; // 提现费
        String rateType = "";
        if (type.equals("P")) {
            // 专业版 0.28
            rateType = "7";
            AvsPayAccess access = avsPayAccessService.queryById("4feaf8e04fa8459cbb44a42b08a9638e");
            rate = access.getRate() * 0.01;
            deposit = access.getDeposit();
            request.setProductVersion(PayConstants.YB_PRODUCT_VERSION_PROFESSIONAL);
        } else if (type.equals("N")) {
            // 标准版 0.38
            rateType = "1";
            AvsPayAccess access = avsPayAccessService.queryById("ffb57769b3ff438ca22e0e9c8c7bda5e");
            rate = access.getRate() * 0.01;
            deposit = access.getDeposit();
            request.setProductVersion(PayConstants.YB_PRODUCT_VERSION_STANDARD);
        } else {
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "交易类型错误:" + type);
        }
        // 修改用户刷卡费率
        RestResponse setFeeResult = updateMerRate(customer.getYbSubMerId(), rateType, new BigDecimal(format.format(rate)).toString());
        if (!setFeeResult.getCode().equals(String.valueOf(HttpStatus.SC_OK)))
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "用户费率有误，请联系客服处理:" + setFeeResult.getResult());
        // 修改用户提现费
        setFeeResult = updateMerRate(customer.getYbSubMerId(), "3", deposit + "");
        if (!setFeeResult.getCode().equals(String.valueOf(HttpStatus.SC_OK)))
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "用户费率有误，请联系客服处理:" + setFeeResult.getResult());
        request.setCallBackUrl(serverUrl + "/thmlfApi/avs/ybpay/paymentNotify");
//        request.setWebCallBackUrl(serverUrl + "/thmlfApi/avs/ybpay/webCallBackUrl");
        request.setWebCallBackUrl(serverUrl + "/pay/cash.html?payerId=" + customer.getCustomerId() + "&appId=" + customer.getAppId());
        request.setPayerBankAccountNo(accessBind.getCardNum());
        RestResponse restResponse = ybService.receive(request);
        if (restResponse.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
            ReceiveResponse response = (ReceiveResponse) restResponse.getResult();
            if (response.getCode().equals("0000"))
                restResponse = RestResponse.build(response.getUrl());
            else
                restResponse = RestResponse.build(RestResponse.AVS_ERROR_CODE, response.getMessage(), response);
        }
        return restResponse;
    }

    // 支付通知
    public String paymentNotify(YbPaymentNotifyRequest request) {
        String hmac = YbPaymentNotifyRequest.signature(request);
        List<AvsPayOrder> orders = orderService.findByOrderNum(request.getRequestId());
        if (orders.isEmpty())
            return "requestId not found";
        AvsPayOrder order = orders.get(0);
        if (order.getStatus() >= Enums.OrderStatusEnum.SUCCESS_DEPOSIT.getValue())
            return "SUCCESS";
        if (request.getStatus().equals("INIT"))
            order.setStatus(Enums.OrderStatusEnum.NO_PAYED.getValue());
        else if (request.getStatus().equals("SUCCESS")) {
            order.setStatus(Enums.OrderStatusEnum.SUCCESS_PAYED.getValue());
            order.setTransDate(new Date());
        } else {
            order.setStatus(Enums.OrderStatusEnum.FAILED.getValue());
        }
        orderService.update(order);
        if (order.getRemark().equals(PayConstants.VIP_CASH)) {
            AvsCustomer customer = customerService.findByCustomerId(order.getPayerId());
            if (customer == null)
                return "user info error";
            List<AvsPayVip> vips = vipService.findByUserId(customer.getCustomerId());
            if (vips.isEmpty())
                return "info error";
            AvsPayVip vip = vips.get(0);
            vip.setPayTime(new Date());
            vip.setMoney(order.getAmountTotal());
            vip.setStatus(AvsPayVipStatus.VipStatus.VIP.getValue());
            vip.setIsDraw(AvsPayVipStatus.DrawStatus.NO.getValue());
            Date nowDate = new Date();
            Calendar c = Calendar.getInstance();
            //一年后
            c.setTime(nowDate);
            c.add(Calendar.YEAR, 1);
            Date nextYear = c.getTime();
            vip.setPayTime(nowDate);
            vip.setEndTime(nextYear);
            vipService.update(vip);
            order.setStatus(Enums.OrderStatusEnum.VIP_SUCCESS.getValue());
            orderService.update(order);
        } else {
            RestResponse restResponse = withDrawApi(order.getOrderNum(), order.getPayerId());
            if (restResponse.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
                orders = orderService.findByOrderNum(order.getOrderNum());
                order = orders.get(0);
                order.setStatus(Enums.OrderStatusEnum.SUCCESS_DEPOSIT.getValue());
                order.setFinishDate(new Date());
                orderService.update(order);
            }
        }
        return "SUCCESS";
    }

    // 提现查询查询
    public RestResponse transferQuery(AvsPayOrder order) {
        AvsCustomer customer = customerService.findByCustomerId(order.getPayerId());
        if (customer == null)
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "用户信息错误");
        WithdrawQueryRequest request = new WithdrawQueryRequest();
        request.setMainCustomerNumber(PayConstants.YB_AGENT_NUMBER);
        request.setCustomerNumber(customer.getYbSubMerId());
        request.setExternalNo(order.getOrderNum());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(order.getCreateDate());
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        request.setRequestDateSectionBegin(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime()));
        calendar.setTime(order.getCreateDate());
        calendar.add(Calendar.DAY_OF_MONTH, 20);
        request.setRequestDateSectionEnd(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime()));
        request.setTransferWay("1");
        request.setPageNo("1");
        request.setHmac(WithdrawQueryRequest.signature(request));
        RestResponse restResponse = ybService.withdrawQuery(request);
        if (restResponse.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
            // 已经发起提现
            if (restResponse != null && restResponse.getResult() != null) {
                WithdrawQueryResponse response = (WithdrawQueryResponse) restResponse.getResult();
                TransferRequest transferRequest = response.getTransferRequests().get(0);
                if (transferRequest.getTransferStatus().equals("SUCCESSED")) {
                    return RestResponse.build("1001", "此订单已经结算成功，如果长时间未到账，请联系客服处理。");
                } else if (transferRequest.getTransferStatus().equals("RECEIVED")) {
                    return RestResponse.build("1002", "通道已经接收此订单结算信息，如果长时间未到账，请联系客服处理。");
                } else if (transferRequest.getTransferStatus().equals("PROCESSING")) {
                    return RestResponse.build("1003", "通道正在处理此订单结算信息，如果长时间未到账，请联系客服处理。");
                } else {
                    return RestResponse.build(RestResponse.AVS_ERROR_CODE, "结算失败或错误:" + transferRequest.getTransferStatus());
                }
            }
        } else if ("1001".equals(restResponse.getCode()) && order.getStatus().equals(Enums.OrderStatusEnum.SUCCESS_PAYED.getValue())) {
            // 未发起提现
            return RestResponse.build("2002", "此订单尚未发起提现");
        }
        return restResponse;
    }


    // 查询子商户是否需要修改结算卡
    public RestResponse querySubMerInfo(String payerId) {
        AvsCustomer customer = customerService.findByCustomerId(payerId);
        if (customer == null)
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "信息有误");
        List<AvsPayCashBind> cashBinds = cashBindService.findByIsDepositAndPayerId(1, payerId);
        if (cashBinds.isEmpty()) {
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "无结算卡信息");
        }
        YbQueryInfoRequest request = new YbQueryInfoRequest();
        request.setCustomerNumber(customer.getYbSubMerId());
        request.setMobilePhone(customer.getPhone());
        RestResponse restResponse = ybService.queryInfo(request);
        if (restResponse.getCode().equals(String.valueOf(HttpStatus.SC_OK))) {
            YbQueryInfoResponse response = (YbQueryInfoResponse) restResponse.getResult();
            String bankNoFrist = cashBinds.get(0).getCardNum().substring(0, 4);
            String bankNoLast = cashBinds.get(0).getCardNum().substring(cashBinds.get(0).getCardNum().length() - 4, cashBinds.get(0).getCardNum().length());
            if (response.getRetList().isEmpty())
                return RestResponse.build(RestResponse.AVS_ERROR_CODE, "商户信息不存在");
            ReturnInfo info = response.getRetList().get(0);
            if (info.getBankAccountNumber().substring(0, 4).equals(bankNoFrist) &&
                    info.getBankAccountNumber().substring(info.getBankAccountNumber().length() - 4,
                            info.getBankAccountNumber().length()).equals(bankNoLast)) {
                return RestResponse.build(response);
            } else {
                return updateDepositCard(customer.getCustomerId(), customer.getYbSubMerId());
            }
        }
        return restResponse;
    }

    // 修改结算卡
    private RestResponse updateDepositCard(String payerId, String subMerId) {
        List<AvsPayCashBind> cashBinds = cashBindService.findByIsDepositAndPayerId(1, payerId);
        if (cashBinds.isEmpty())
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "无结算卡信息");
        EditMerchantRequest request = new EditMerchantRequest();
        request.setCustomerNumber(subMerId);
        request.setModifyType("2"); // 2 修改银行信息
        request.setBankCardNumber(cashBinds.get(0).getCardNum());
        request.setBankName(cashBinds.get(0).getBankName());
        return ybService.editMerchant(request);
    }

    // 结算提现
    public RestResponse withDrawApi(String orderNum, String payerId) {
        List<AvsPayOrder> orders = orderService.findByOrderNum(orderNum);
        if (orders.isEmpty())
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "订单信息不存在");
        AvsCustomer customer = customerService.findByCustomerId(payerId);
        AvsPayOrder order = orders.get(0);
        if (!order.getStatus().equals(Enums.OrderStatusEnum.SUCCESS_PAYED.getValue())) {
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "此订单不满足提现");
        }
        if (!order.getPayerId().equals(payerId)) {
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "提现信息有误");
        }
        if (customer.getYbSubMerId() == null)
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "提现信息有误");
        List<AvsPayCashBind> cashBinds = cashBindService.findByIsDepositAndPayerId(1, payerId);
        if (cashBinds.isEmpty())
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "未绑定结算卡");
        order.setCollecBank(cashBinds.get(0).getBankName());
        order.setCashCardNo(cashBinds.get(0).getCardNum());
        orderService.update(order);
        RestResponse restResponse = querySubMerInfo(payerId);
        if (!restResponse.getCode().equals(String.valueOf(HttpStatus.SC_OK)))
            return restResponse;
        Double amount = order.getRealAmount();
//        AvsPayAccess access = avsPayAccessService.queryById("4feaf8e04fa8459cbb44a42b08a9638e");
        DecimalFormat decimalFormat = new DecimalFormat("0.##");
        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        List<AvsPayAccess> accessList = avsPayAccessService.queryByAccessId(order.getAccessId());
        if (accessList.isEmpty())
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "通道不存在");
        WithdrawRequest request = new WithdrawRequest();
        request.setAmount(decimalFormat.format(amount + accessList.get(0).getDeposit()));
        request.setTransferWay("1"); // 1 T0  2 T1
        request.setExternalNo(order.getOrderNum());
        request.setCustomerNumber(customer.getYbSubMerId());
        request.setCallBackUrl(serverUrl + "/thmlfApi/avs/ybpay/withDrawNotify");
        return ybService.withdraw(request);
    }

    // 查询用户余额
    public RestResponse balanceQuery(String payerId, String type) {
        AvsCustomer customer = customerService.findByCustomerId(payerId);
        if (customer == null)
            return RestResponse.build(RestResponse.AVS_ERROR_CODE, "用户信息错误");
        return ybService.balanceQuery(customer.getYbSubMerId(), type);
    }

    // 设置商户费率
    public RestResponse updateMerRate(String subMerNo, String type, String value) {
        FeeSetRequest request = new FeeSetRequest();
        request.setCustomerNumber(subMerNo);
        request.setMainCustomerNumber(PayConstants.YB_AGENT_NUMBER);
        request.setProductType(type);
        request.setRate(value);
        request.setHmac(FeeSetRequest.signature(request));
        RestResponse restResponse = ybService.feeSet(request);
        return restResponse;
    }

    // 费率查询
    public RestResponse merFeeQuery(String merNo, String type) {
        MerFeeQueryRequest request = new MerFeeQueryRequest();
        request.setCustomerNumber(merNo);
        request.setProductType(type);
        return ybService.feeQuery(request);
    }

    // 提现通知
    public String withDrawNotify(YbPayWithDrawRequest request) {
        String hmac = YbPayWithDrawRequest.signature(request);
        System.out.println("提现通知：" + new Gson().toJson(request));
        List<AvsPayOrder> orders = orderService.findByOrderNum(request.getExternalNo());
        if (orders.isEmpty())
            return "error";
        AvsPayOrder order = orders.get(0);
        if (order.getStatus() >= Enums.OrderStatusEnum.SUCCESS_DEPOSIT.getValue())
            return "SUCCESS";
        if (request.getTransferStatus().equals("RECEIVED")) {
            // 已接受
        } else if (request.getTransferStatus().equals("PROCESSING")) {
            // 处理中
        } else if (request.getTransferStatus().equals("SUCCESSED")) {
            // 打款成功
            order.setStatus(Enums.OrderStatusEnum.SUCCESS_DEPOSIT.getValue());
            order.setFinishDate(new Date());
            order.setCashCardNo(request.getReceiverBankCardNo());
            order.setCollecBank(request.getReceiverBank());
        } else if (request.getTransferStatus().equals("FAILED")) {
            // 打款失败
        } else if (request.getTransferStatus().equals("REFUNED")) {
            // 已退款
        } else if (request.getTransferStatus().equals("CANCELLED")) {
            // 已撤销
        }
        orderService.update(order);
        return "SUCCESS";
    }

}
